#!/usr/bin/python
# coding=utf-8
import socket
from threading import Thread

UDP_IP = "<broadcast>"
UDP_PORT = 5748
UDP_PORT_CLIENT = 5749
LOCAL_IP = "localhost"  # TO MODIFY


# Les variable de Key sont les "Headers" du protocole
class Key:
    SOURCE = 'S'
    DESTINATION = 'D'
    PORT = 'P'
    TYPE = 'T'
    CONTENT = 'C'


# Les variables de Type représentent le type de message envoyé
class Type:
    AUTHORIZE = 'A'
    DEAUTHORIZE = 'D'
    TEXT = 'T'
    RESULT = 'R'
    COMMAND = 'C'
    # FILE = 'F'


class Result:
    OK = 'O'
    DENIED = 'X'
    ERROR = 'E'
    WARNING = 'W'


class Message:
    # Transforme un dictionnaire en String (pour l'analyze du protocole)
    def toString(msg_dict):
        s = ''
        for (k, v) in msg_dict.items():
            s += k + ":" + str(v) + ";"
        return s[:-1]

    # Transforme un string en dictionnaire (pour le protocole)
    def toDictionnary(msg_str):
        key_values = msg_str.split(';')
        msg = {}
        for key_value in key_values:
            pair = key_value.split(':')
            # 0 est la clé , 1 la valeur
            msg[pair[0]] = pair[1]
        return msg

    # Crée un dictionnaire à partir des différentes variables du message.
    def create(source, destination, port, type, content):
        return {Key.SOURCE: source,
                Key.DESTINATION: destination,
                Key.PORT: port,
                Key.TYPE: type,
                Key.CONTENT: content}


def createMessage(destination, type, content):
    msg = Message.create(user, destination, UDP_PORT, type, content)
    return bytes(Message.toString(msg), 'UTF-8')


def ipSplitter(addr):
    ip, port = addr;
    return ip;


def portSplitter(addr):
    ip, port = addr;
    return port;

sock = socket.socket(socket.AF_INET,  # Internet
                     socket.SOCK_DGRAM)  # UDP

sock.bind(('', UDP_PORT_CLIENT))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)


def decode(msg):
    print(msg[Key.SOURCE] + " says : " + msg[Key.CONTENT])


class MessageThread(Thread):
    def __init__(self):
        Thread.__init__(self)

    def run(self):
        while True:
            data, addr = sock.recvfrom(1024)  # buffer size is 1024 bytes
            ip, port = addr
            decode(Message.toDictionnary(str(data, "utf-8")))

class InputThread(Thread):
    def __init__(self):
        Thread.__init__(self)

    def run(self):
        while True:
            msg = input(">")
            dest = input("à >")

            msg = createMessage(dest, str(Type.TEXT), msg)

            sock.sendto(msg, (UDP_IP, UDP_PORT))

            data, addr = sock.recvfrom(1024)
            msg = Message.toDictionnary(str(data, 'UTF-8'))
            print(msg[Key.CONTENT])



try:
    user = input("Username: ")

    msg = createMessage("SERVER", str(Type.AUTHORIZE), user)
    sock.sendto(msg, (UDP_IP, UDP_PORT))
    data, serveraddr = sock.recvfrom(1024)

    thread1 = MessageThread()
    thread2 = InputThread()

    thread1.start()
    thread2.start()


    thread1.join()
    thread2.join()

    while True:
        pass

    #while True:
    #    data, addr = sock.recvfrom(1024)  # buffer size is 1024 bytes
    #    ip, port = addr
    #    decode(Message.toDictionnary(str(data, "utf-8")))
except:
    print("Fin du programme")

sock.sendto(createMessage("SERVER", str(Type.DEAUTHORIZE), user), (UDP_IP, UDP_PORT))

